/*
 * Startup.java
 */

package choreganizer;

import java.awt.Component;
import java.awt.MenuItem;
import java.awt.SystemTray;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.util.EventObject;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.UIManager;
import org.jdesktop.application.Application;
import org.jdesktop.application.SingleFrameApplication;

import java.sql.SQLException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.util.List;
import javax.swing.JOptionPane;
import org.hsqldb.DatabaseManager;


/**
 * The main class of the application.
 */
public class Startup extends SingleFrameApplication {
    
    private java.awt.Image icon;
    private java.awt.SystemTray tray;
    private java.awt.TrayIcon trayIcon;
    private java.awt.PopupMenu popup;
    // send msg example
    //trayIcon.displayMessage("Restore", "Restore Window", TrayIcon.MessageType.INFO);
	    
    /**
     * At startup create and show the main frame of the application.
     */
    @Override protected void startup() {
	
	// Set our L&F
	try {
	    JFrame.setDefaultLookAndFeelDecorated(true);
	    JDialog.setDefaultLookAndFeelDecorated(true);
	    
	    com.lipstikLF.LipstikLookAndFeel.setMyCurrentTheme(
		    new com.lipstikLF.theme.LightGrayTheme());
	    UIManager.setLookAndFeel("com.lipstikLF.LipstikLookAndFeel");
	} catch (Exception e) {
	    System.err.println("Unable to load native look and feel");
	}
	
	setupDB();
	// We'll need to see if there's an account, and prompt for the user to create
	// one immediatly if there isn't one (or we can just make a dummy account with
	// a blank password and let them modify it later.  Might want a switch on the
	// account table specifying that it's not PW protected)
	// if (noAccountsExist())
	createDBAccount();
	readDB();
	
	
	
	// Setup our window and show it
	this.addExitListener(new ConfirmExit());
	show(new MainFrame(this));
	// These lines ensure the stored frame session doesn't screw things up
	// if the user exits the program while it's in the system tray
	this.getMainFrame().setMinimumSize(new java.awt.Dimension(200,200));
	this.getMainFrame().setState(java.awt.Frame.NORMAL);
	this.getMainFrame().setVisible(true);
    }

    /**
     * This method is to initialize the specified window by injecting resources.
     * Windows shown in our application come fully initialized from the GUI
     * builder, so this additional configuration is not needed.
     */
    @Override protected void configureWindow(java.awt.Window root) {
	// Load the window icon from our resource bundle
	org.jdesktop.application.ResourceMap resourceMap = 
		org.jdesktop.application.Application.getInstance(
		    choreganizer.Startup.class).getContext().getResourceMap(
			Startup.class);
	icon = resourceMap.getImageIcon("Application.icon").getImage();
	resourceMap = null;
	root.setIconImage(icon);
	
	// Setup our tray icon
	root.addWindowListener(new WindowAdapter() {
	    @Override
	    public void windowIconified(java.awt.event.WindowEvent e) {
		new Minimizer().run();
		return;
	    }
	});
    }

    /**
     * A convenient static getter for the application instance.
     * @return the instance of Startup
     */
    public static Startup getApplication() {
        return Application.getInstance(Startup.class);
    }

    /**
     * Main method launching the application.
     * @param args 
     */
    public static void main(String[] args) {
        launch(Startup.class, args);
    }
    
    /*
     * This class will setup our SystemTray in the EDT thread
     */
    class Minimizer extends javax.swing.SwingWorker {

	@Override
	protected Object doInBackground() {
	    if (SystemTray.isSupported()) {
		
		popup = new java.awt.PopupMenu();
		MenuItem item = new MenuItem("Restore");
		item.addActionListener(new ActionListener() {
		    @Override
		    public void actionPerformed(ActionEvent e) {
			tray.remove(trayIcon);
			Startup.this.getMainFrame().setState(java.awt.Frame.NORMAL);
			Startup.this.getMainFrame().toFront();
			Startup.this.getMainFrame().setVisible(true);
			tray = null;
			trayIcon = null;
			popup = null;
		    }
		});
		popup.add(item);

		item = new MenuItem("Close");
		item.addActionListener(new ActionListener() {
		    @Override
		    public void actionPerformed(ActionEvent e) {
			Startup.this.getApplication().exit();
		    }
		});
		popup.add(item);

		try {
		    tray = SystemTray.getSystemTray();
		    trayIcon = new java.awt.TrayIcon(icon, "Choreganizer", popup);
		    tray.add(trayIcon);
		    Startup.this.getMainFrame().setVisible(false);
		} catch (java.awt.AWTException e) {
		    System.err.println("Can't add to tray");
		}
	    }
	    
	    return null;
	}
    }
    
    /*
     * Listen for quit events, and ask the user if they wish to exit, and perform
     * any necessary cleanup
     */
    class ConfirmExit implements Application.ExitListener 
    {
	/**
	 * Ask the user to confirm whether or not they wish to really exit
	 * 
	 * @param e
	 * @return
	 */
	@Override
	public boolean canExit(EventObject e) {
	    Object source = (e != null) ? e.getSource() : null;
	    Component owner = (source instanceof Component) ? (Component)source : null;
	    int option = JOptionPane.showConfirmDialog(owner, "Really Exit?");
	    return option == JOptionPane.YES_OPTION;
	}

	/**
	 * Perform any necessary cleanup before we actually shut down
	 * 
	 * @param e
	 */
	@Override
	public void willExit(EventObject e) {
	    // Perform any cleanup here
	}
    }
 
    /*
     * We'll want to do this even when the DB already exists.  It won't overwrite or
     * alter the existing table, so we're ok
     */
    public void setupDB()
    {
	try {
	    Class.forName("org.hsqldb.jdbcDriver");
	    Connection connection = DriverManager.getConnection("jdbc:hsqldb:file:./.choreganizer/choreDB", "sa", "");
	    
	    String sql = 
		"create table \"PUBLIC\".ACCOUNTS (" +
		    "ID IDENTITY not null primary key," +
		    "USERNAME VARCHAR(32) default 'New User' not null," +
		    "PASSWORD VARCHAR(32)," +
		    "CREATED TIMESTAMP default NOW, " +
		    "CONSTRAINT UNIQUE_ACCOUNT UNIQUE (USERNAME)" +
		");";
	    boolean q = connection.createStatement().execute(sql);

	    // Shutdown the database normally (0), or shutdown and script out using (2)
	    DatabaseManager.closeDatabases(0);
	    
	    connection.close();
	} catch (SQLException sqlEx) {
	    // Error executing statement
	} catch (ClassNotFoundException cnfEx) {
	    // Can't find our HSQLDB driver
	}
    }
    
    public void createDBAccount()
    {
	try {
	    Class.forName("org.hsqldb.jdbcDriver");
	    Connection connection = DriverManager.getConnection("jdbc:hsqldb:file:./.choreganizer/choreDB", "sa", "");

	    String sql = 
		"INSERT INTO \"PUBLIC\".ACCOUNTS " +
		"   (USERNAME, PASSWORD)" +
		"VALUES" +
		"   ('jim', 'testpass')";
	    boolean q = connection.createStatement().execute(sql);
	    
	    // Shutdown the database normally (0), or shutdown and script out using (2)
	    DatabaseManager.closeDatabases(0);
	    
	    connection.close();
	} catch (SQLException sqlEx) {
	    // Error executing statement
	} catch (ClassNotFoundException cnfEx) {
	    // Can't find our HSQLDB driver
	}
    }
    
    public void readDB()
    {
	try {
	    Class.forName("org.hsqldb.jdbcDriver");
	    Connection connection = DriverManager.getConnection("jdbc:hsqldb:file:./.choreganizer/choreDB", "sa", "");

	    // Fetch all of the known database URIs and display them
	    List v = DatabaseManager.getDatabaseURIs();
	    for (Object o : v)
		System.out.println("DB Exists - "+((String) o));

	    ResultSet r = connection.createStatement().executeQuery(
		"SELECT * FROM \"PUBLIC\".ACCOUNTS");
	    while (r.next())
	    {
		System.out.println(r.getString(1) + " - " + r.getString(2));
	    }
	    
	    // Shutdown the database normally (0), or shutdown and script out using (2)
	    DatabaseManager.closeDatabases(0);
	    
	    connection.close();
	} catch (SQLException sqlEx) {
	    // Error executing statement
	} catch (ClassNotFoundException cnfEx) {
	    // Can't find our HSQLDB driver
	}
    }
}